/*
 * This file is part of TradeHelper library.
 *
 * TradeHelper library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * TradeHelper library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with TradeHelper library.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.rag.forum.pages;

import com.alee.extended.label.WebLinkLabel;
import com.alee.extended.layout.HorizontalFlowLayout;
import com.alee.extended.layout.WrapFlowLayout;
import com.alee.extended.panel.CollapsiblePaneAdapter;
import com.alee.extended.panel.GroupPanel;
import com.alee.extended.panel.WebCollapsiblePane;
import com.alee.laf.button.WebToggleButton;
import com.alee.laf.label.WebLabel;
import com.alee.laf.panel.WebPanel;
import com.alee.laf.separator.WebSeparator;
import com.alee.laf.toolbar.WhiteSpace;
import com.alee.managers.settings.SettingsManager;
import com.alee.utils.SwingUtils;
import com.rag.core.*;
import com.rag.managers.FavoritesManager;
import com.rag.managers.RagManager;
import com.rag.utils.RagUtils;
import info.clearthought.layout.TableLayout;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * User: mgarin Date: 18.06.12 Time: 19:40
 */

public class TopicContentPanel extends WebCollapsiblePane
{
    public static ImageIcon favoriteIcon =
            new ImageIcon ( TopicContentPanel.class.getResource ( "icons/forum/favorite.png" ) );
    public static ImageIcon nonfavoriteIcon =
            new ImageIcon ( TopicContentPanel.class.getResource ( "icons/forum/nonfavorite.png" ) );

    public static ImageIcon replyIcon =
            new ImageIcon ( TopicContentPanel.class.getResource ( "icons/forum/reply.png" ) );

    public static ImageIcon info24 =
            new ImageIcon ( TopicContentPanel.class.getResource ( "icons/forum/info24.png" ) );
    public static ImageIcon closed24 =
            new ImageIcon ( TopicContentPanel.class.getResource ( "icons/forum/closed24.png" ) );
    public static ImageIcon guild24 =
            new ImageIcon ( TopicContentPanel.class.getResource ( "icons/forum/guild24.png" ) );

    private ForumType forumType;
    private SingleTopicData topicData;
    private List<SingleTopicData> topicsData;

    private boolean groupItems;
    private boolean wrapItems;
    private boolean showItemId;
    private boolean showTopicNumber;

    private WebToggleButton favorite;

    public TopicContentPanel ( final ForumType forumType, final SingleTopicData topicData,
                               List<SingleTopicData> topicsData, boolean groupItems,
                               boolean wrapItems, boolean showItemId, boolean showTopicNumber )
    {
        super ();

        // Базовые настройки отображения топика
        this.forumType = forumType;
        this.topicData = topicData;
        this.topicsData = topicsData;
        this.groupItems = groupItems;
        this.wrapItems = wrapItems;
        this.showItemId = showItemId;
        this.showTopicNumber = showTopicNumber;

        // Настройки разворачиваемой панели
        setAnimate ( false );
        setWebColored ( false );
        setShadeWidth ( 0 );
        setDrawSides ( false, false, true, false );
        setExpanded ( isExpanded ( forumType, topicData.getId () ) );
        addCollapsiblePaneListener ( new CollapsiblePaneAdapter ()
        {
            public void expanded ( WebCollapsiblePane pane )
            {
                setExpanded ( forumType, topicData.getId (), true );
            }

            public void collapsed ( WebCollapsiblePane pane )
            {
                setExpanded ( forumType, topicData.getId (), false );
            }
        } );

        // Панель заголовка топика
        final WebPanel topicTitlePanel = new WebPanel ();
        topicTitlePanel.setOpaque ( false );
        topicTitlePanel.setMargin ( 5 );
        setTitleComponent ( topicTitlePanel );

        // Кнопка добавления в избранное
        favorite = new WebToggleButton ();
        favorite.setIcon ( nonfavoriteIcon );
        favorite.setSelectedIcon ( favoriteIcon );
        favorite.setUndecorated ( true );
        favorite.setLeftRightSpacing ( 0 );
        favorite.setSelected ( FavoritesManager.isFavorite ( topicData ) );
        favorite.addActionListener ( new ActionListener ()
        {
            public void actionPerformed ( ActionEvent e )
            {
                if ( favorite.isSelected () )
                {
                    FavoritesManager.addFavoriteTopic ( topicData );
                }
                else
                {
                    FavoritesManager.removeFavoriteTopic ( topicData );
                }
            }
        } );

        // Ссылка на топик с его названием
        WebLinkLabel topicTitle = RagUtils.createTopicInfoLink ( topicData );

        // Кол-во ответов на топик
        WebLabel replyCount = new WebLabel (
                topicData.getReplyCount () != null && topicData.getReplyCount () > 0 ?
                        "" + topicData.getReplyCount () : "нет", replyIcon );

        // Определяем номер топика среди остальных
        final String topicNumberText;
        if ( showTopicNumber )
        {
            int tn = 0;
            for ( int i = 0; i < topicsData.size (); i++ )
            {
                if ( topicsData.get ( i ).getId ().equals ( topicData.getId () ) )
                {
                    tn = i + 1;
                    break;
                }
            }
            topicNumberText = showTopicNumber ? ( tn + "." ) : "";
        }
        else
        {
            topicNumberText = "";
        }

        // Заголовок топика
        if ( groupItems )
        {
            WebLabel number = new WebLabel ( topicNumberText, WebLabel.RIGHT )
            {
                public Dimension getPreferredSize ()
                {
                    Dimension ps = super.getPreferredSize ();
                    ps.width = 80 - topicTitlePanel.getMargin ().left;
                    return ps;
                }
            };
            topicTitlePanel.add ( new GroupPanel ( 4, favorite, SwingUtils.boldFont ( number ),
                    new WhiteSpace ( 8, WhiteSpace.HORIZONTAL ), topicTitle,
                    SwingUtils.boldFont ( replyCount ) ), BorderLayout.WEST );
        }
        else
        {
            topicTitlePanel.add ( new GroupPanel ( 4, favorite,
                    SwingUtils.boldFont ( new WebLabel ( topicNumberText ) ), topicTitle,
                    replyCount ), BorderLayout.WEST );
        }

        // Ссылка на профиль автора топика
        WebLinkLabel userInfo = RagUtils.createUserInfo ( topicData.getUser () );
        topicTitlePanel.add ( SwingUtils.boldFont ( userInfo ), BorderLayout.EAST );

        // Список итемов
        JComponent content = createParsedItemsList ();
        if ( topicData.getTopicType ().equals ( TopicType.closed ) )
        {
            content.setBackground ( new Color ( 255, 200, 200 ) );
        }
        setContent ( content );
    }

    /**
     * Методы для получения и изменения настроек отображения топика
     */

    public SingleTopicData getTopicData ()
    {
        return topicData;
    }

    public void setFavorite ( boolean favorite )
    {
        this.favorite.setSelected ( favorite );
    }

    public boolean isFavorite ()
    {
        return favorite.isSelected ();
    }

    public boolean isWrapItems ()
    {
        return wrapItems;
    }

    public void setWrapItems ( boolean wrapItems )
    {
        this.wrapItems = wrapItems;
        revalidate ();
    }

    /**
     * Методы создания отображения списка итемов топика
     */

    private JComponent createParsedItemsList ()
    {
        if ( topicData.getParsedItems ().size () > 0 )
        {
            // Список итемов
            List<ItemData> itemsData = topicData.getParsedItems ();
            return createParsedItemsList ( itemsData, groupItems, wrapItems, showItemId );
        }
        else
        {
            // Информационное сообщение
            WebLabel infoLabel;
            if ( topicData.getTopicType ().equals ( TopicType.closed ) )
            {
                infoLabel = new WebLabel ( "Топик закрыт", closed24 );
            }
            else if ( topicData.getTopicType ().equals ( TopicType.guild ) )
            {
                infoLabel = new WebLabel ( "Операции с гильдией", guild24 );
            }
            else
            {
                infoLabel = new WebLabel ( "Не удалось определить содержимое", info24 );
            }

            if ( groupItems )
            {
                WebPanel groupPanel = new WebPanel ();
                TableLayout layout = new TableLayout (
                        new double[][]{ { 100, TableLayout.PREFERRED, TableLayout.FILL },
                                { TableLayout.PREFERRED } } );
                layout.setHGap ( 5 );
                layout.setVGap ( 5 );
                groupPanel.setLayout ( layout );

                groupPanel.add ( new WebLabel ( "Other", WebLabel.RIGHT ), "0,0" );
                groupPanel.add ( new WebSeparator ( false, WebSeparator.VERTICAL ), "1,0" );
                groupPanel.add ( infoLabel, "2,0" );

                groupPanel.setMargin ( 4 );
                return groupPanel;
            }
            else
            {
                infoLabel.setMargin ( 4 );
                return infoLabel;
            }
        }
    }

    private JComponent createParsedItemsList ( List<ItemData> itemsData, boolean groupItems,
                                               boolean wrapItems, boolean showItemId )
    {
        if ( groupItems )
        {
            // Групирруем данные
            Map<ItemType, List<ItemData>> groupedData = new HashMap<ItemType, List<ItemData>> ();
            for ( ItemData data : itemsData )
            {
                // Находим итем
                Item item = RagManager.getItem ( data.getItemId () );

                // Создаём список по типу, если необходимо
                if ( !groupedData.containsKey ( item.getItemType () ) )
                {
                    groupedData.put ( item.getItemType (), new ArrayList<ItemData> () );
                }

                // Добавляем в него итем
                groupedData.get ( item.getItemType () ).add ( data );
            }

            // Создаём группы
            double[] rows = new double[ groupedData.size () * 2 - 1 ];
            for ( int i = 0; i < rows.length; i++ )
            {
                rows[ i ] = TableLayout.PREFERRED;
            }
            TableLayout layout = new TableLayout (
                    new double[][]{ { 100, TableLayout.PREFERRED, TableLayout.FILL }, rows } );
            layout.setHGap ( 5 );
            layout.setVGap ( 5 );

            WebPanel content = new WebPanel ( layout );
            content.setMargin ( 3 );
            content.add ( new WebSeparator ( false, WebSeparator.VERTICAL ),
                    "1,0,1," + ( rows.length - 1 ) );

            int row = 0;
            for ( ItemType itemType : groupedData.keySet () )
            {
                content.add ( new WebLabel ( itemType.getTypeName (), WebLabel.RIGHT ),
                        "0," + row );

                WebPanel typePanel = new WebPanel ( getWrapLayout () )
                {
                    public Dimension getPreferredSize ()
                    {
                        Dimension ps = super.getPreferredSize ();
                        ps.width = 0;
                        return ps;
                    }
                };
                for ( ItemData data : groupedData.get ( itemType ) )
                {
                    typePanel.add ( createItemView ( data, showItemId ) );

                }
                content.add ( typePanel, "2," + row );

                if ( row < rows.length - 1 )
                {
                    content.add ( new WebSeparator ( false, WebSeparator.HORIZONTAL ),
                            "0," + ( row + 1 ) + ",2," + ( row + 1 ) );
                }
                row += 2;
            }

            return content;
        }
        else
        {
            WebPanel content = new WebPanel ( getWrapLayout () )
            {
                public Dimension getPreferredSize ()
                {
                    Dimension ps = super.getPreferredSize ();
                    ps.width = 0;
                    return ps;
                }
            };
            content.setMargin ( 3 );
            for ( ItemData data : itemsData )
            {
                content.add ( createItemView ( data, showItemId ) );
            }
            return content;
        }
    }

    private LayoutManager getWrapLayout ()
    {
        return new WrapFlowLayout ( false, 15, 4 )
        {
            public boolean isWrapEachComponent ()
            {
                return wrapItems;
            }
        };
    }

    /**
     * Метод создания отображения одного итема
     */

    private JComponent createItemView ( ItemData data, boolean showItemId )
    {
        WebPanel view = new WebPanel ();
        view.setLayout ( new HorizontalFlowLayout ( 4, false ) );

        // Добавляем представление итема
        view.add ( RagUtils.createItemInfoLink ( data ) );

        // Добавляем представление карт
        List<String> cardIds = data.getCardIds ();
        if ( cardIds != null && cardIds.size () > 0 )
        {
            view.add ( SwingUtils.fontSize ( new WebLabel ( "[" ), 14 ) );

            List<String> addedIds = new ArrayList<String> ();
            for ( int i = 0; i < cardIds.size (); i++ )
            {
                String id = cardIds.get ( i );

                // Пропускаем повторные карты, они уже были обработаны при первом вхождении
                if ( addedIds.contains ( id ) )
                {
                    continue;
                }

                // Вычисляем количество одинаковых карт с данным ID
                int amount = RagUtils.getCardsAmount ( id, cardIds );
                addedIds.add ( id );

                // Добавляем описание карты
                WebLinkLabel cardLink = RagUtils.createItemInfoLink ( id );
                if ( amount > 1 )
                {
                    // Добавляем кол-во карт данного типа
                    view.add ( new GroupPanel ( new WebLabel ( " " + amount + "x" ), cardLink ) );
                }
                else
                {
                    // Просто добавляем описание карты
                    view.add ( cardLink );
                }

                if ( data.getSlotCount () != null && data.getSlotCount () < cardIds.size () &&
                        i < cardIds.size () - 1 && RagUtils.isAnyCardsLeft ( cardIds, addedIds ) )
                {
                    view.add ( new WebLabel ( " или " ) );
                }
            }

            view.add ( SwingUtils.fontSize ( new WebLabel ( "]" ), 14 ) );
        }

        // Добавляем ссылку на копирование ID итема
        if ( showItemId )
        {
            view.add ( RagUtils.createIdLink ( data.getItemId () ) );
        }

        return view;
    }

    /**
     * Методы для чтения и сохранения состояния развёрнутости панелей топиков
     */

    private void setExpanded ( ForumType forumType, String topicId, boolean expanded )
    {
        List<String> collapsedList = getCollapsedList ();
        if ( expanded )
        {
            collapsedList.remove ( getFullTopicId ( forumType, topicId ) );
        }
        else
        {
            collapsedList.add ( getFullTopicId ( forumType, topicId ) );
        }
        saveCollapsedList ( collapsedList );
    }

    private boolean isExpanded ( ForumType forumType, String topicId )
    {
        return !getCollapsedList ().contains ( getFullTopicId ( forumType, topicId ) );
    }

    private String getFullTopicId ( ForumType forumType, String topicId )
    {
        return forumType + ":" + topicId;
    }

    private List<String> getCollapsedList ()
    {
        return SettingsManager.getSettings ( "CollapsedTopics.xml", new ArrayList<String> () );
    }

    private void saveCollapsedList ( List<String> collapsedList )
    {
        SettingsManager.setSettings ( "CollapsedTopics.xml", collapsedList );
    }
}